using Microsoft.Extensions.Configuration;
using SeataNet.Core.Configuration;

namespace SeataNet.Core.Configuration
{
    /// <summary>
    /// Seata配置扩展
    /// </summary>
    public static class SeataConfigurationExtensions
    {
        /// <summary>
        /// 从配置文件加载配置
        /// </summary>
        /// <param name="configuration">配置对象</param>
        /// <param name="configurationSection">配置节</param>
        /// <returns>配置对象</returns>
        public static SeataConfiguration LoadFromConfiguration(this SeataConfiguration configuration, IConfiguration configurationSection)
        {
            if (configurationSection == null)
            {
                throw new ArgumentNullException(nameof(configurationSection));
            }
            
            // 加载基本配置
            configuration.ApplicationId = configurationSection["ApplicationId"] ?? configuration.ApplicationId;
            configuration.TransactionServiceGroup = configurationSection["TransactionServiceGroup"] ?? configuration.TransactionServiceGroup;
            
            // 加载传输配置
            var transportSection = configurationSection.GetSection("Transport");
            if (transportSection.Exists())
            {
                configuration.Transport.ServerAddress = transportSection["ServerAddress"] ?? configuration.Transport.ServerAddress;
                configuration.Transport.HeartbeatInterval = int.TryParse(transportSection["HeartbeatInterval"], out var heartbeatInterval) 
                    ? heartbeatInterval 
                    : configuration.Transport.HeartbeatInterval;
                configuration.Transport.Serialization = transportSection["Serialization"] ?? configuration.Transport.Serialization;
                configuration.Transport.Compressor = transportSection["Compressor"] ?? configuration.Transport.Compressor;
            }
            
            // 加载数据库代理配置
            var databaseProxySection = configurationSection.GetSection("DatabaseProxy");
            if (databaseProxySection.Exists())
            {
                configuration.DatabaseProxy.DataSource = databaseProxySection["DataSource"] ?? configuration.DatabaseProxy.DataSource;
                configuration.DatabaseProxy.UserName = databaseProxySection["UserName"] ?? configuration.DatabaseProxy.UserName;
                configuration.DatabaseProxy.Password = databaseProxySection["Password"] ?? configuration.DatabaseProxy.Password;
                configuration.DatabaseProxy.MinPoolSize = int.TryParse(databaseProxySection["MinPoolSize"], out var minPoolSize) 
                    ? minPoolSize 
                    : configuration.DatabaseProxy.MinPoolSize;
                configuration.DatabaseProxy.MaxPoolSize = int.TryParse(databaseProxySection["MaxPoolSize"], out var maxPoolSize) 
                    ? maxPoolSize 
                    : configuration.DatabaseProxy.MaxPoolSize;
            }
            
            return configuration;
        }
        
        /// <summary>
        /// 从环境变量加载配置
        /// </summary>
        /// <param name="configuration">配置对象</param>
        /// <returns>配置对象</returns>
        public static SeataConfiguration LoadFromEnvironment(this SeataConfiguration configuration)
        {
            // 加载基本配置
            configuration.ApplicationId = Environment.GetEnvironmentVariable("SEATA_APPLICATION_ID") ?? configuration.ApplicationId;
            configuration.TransactionServiceGroup = Environment.GetEnvironmentVariable("SEATA_TRANSACTION_SERVICE_GROUP") ?? configuration.TransactionServiceGroup;
            
            // 加载传输配置
            configuration.Transport.ServerAddress = Environment.GetEnvironmentVariable("SEATA_SERVER_ADDRESS") ?? configuration.Transport.ServerAddress;
            configuration.Transport.HeartbeatInterval = int.TryParse(Environment.GetEnvironmentVariable("SEATA_HEARTBEAT_INTERVAL"), out var heartbeatInterval) 
                ? heartbeatInterval 
                : configuration.Transport.HeartbeatInterval;
            configuration.Transport.Serialization = Environment.GetEnvironmentVariable("SEATA_SERIALIZATION") ?? configuration.Transport.Serialization;
            configuration.Transport.Compressor = Environment.GetEnvironmentVariable("SEATA_COMPRESSOR") ?? configuration.Transport.Compressor;
            
            // 加载数据库代理配置
            configuration.DatabaseProxy.DataSource = Environment.GetEnvironmentVariable("SEATA_DATASOURCE") ?? configuration.DatabaseProxy.DataSource;
            configuration.DatabaseProxy.UserName = Environment.GetEnvironmentVariable("SEATA_USERNAME") ?? configuration.DatabaseProxy.UserName;
            configuration.DatabaseProxy.Password = Environment.GetEnvironmentVariable("SEATA_PASSWORD") ?? configuration.DatabaseProxy.Password;
            configuration.DatabaseProxy.MinPoolSize = int.TryParse(Environment.GetEnvironmentVariable("SEATA_MIN_POOL_SIZE"), out var minPoolSize) 
                ? minPoolSize 
                : configuration.DatabaseProxy.MinPoolSize;
            configuration.DatabaseProxy.MaxPoolSize = int.TryParse(Environment.GetEnvironmentVariable("SEATA_MAX_POOL_SIZE"), out var maxPoolSize) 
                ? maxPoolSize 
                : configuration.DatabaseProxy.MaxPoolSize;
            
            return configuration;
        }
        
        /// <summary>
        /// 验证配置
        /// </summary>
        /// <param name="configuration">配置对象</param>
        /// <returns>验证结果</returns>
        public static bool Validate(this SeataConfiguration configuration)
        {
            if (string.IsNullOrEmpty(configuration.ApplicationId))
            {
                return false;
            }
            
            if (string.IsNullOrEmpty(configuration.TransactionServiceGroup))
            {
                return false;
            }
            
            if (string.IsNullOrEmpty(configuration.Transport.ServerAddress))
            {
                return false;
            }
            
            return true;
        }
        
        /// <summary>
        /// 获取验证错误信息
        /// </summary>
        /// <param name="configuration">配置对象</param>
        /// <returns>验证错误信息</returns>
        public static string GetValidationError(this SeataConfiguration configuration)
        {
            var errors = new List<string>();
            
            if (string.IsNullOrEmpty(configuration.ApplicationId))
            {
                errors.Add("ApplicationId is required");
            }
            
            if (string.IsNullOrEmpty(configuration.TransactionServiceGroup))
            {
                errors.Add("TransactionServiceGroup is required");
            }
            
            if (string.IsNullOrEmpty(configuration.Transport.ServerAddress))
            {
                errors.Add("ServerAddress is required");
            }
            
            return string.Join(", ", errors);
        }
    }
}